import React from 'react';
import Canvas from '../../core/Canvas';
import AxisLayer from '../../layer/AxisLayer';
import KBarLayer from '../../layer/KBarLayer';
import Event from '../../event/Event';
import AccelerateAction from '../../action/AccelerateAction';
import IndicatorLayer from "../../layer/IndicatorLayer";
import DrawLayer from '../../layer/DrawLayer';
import OChart from '../../core/OChart';
import PriceLine from '../../layer/PriceLayer';
import CurveLayer from '../../layer/CurveLayer';
import OverlyingLayer from '../../layer/OverlyingLayer';
import HorizonLayer from '../../layer/HorizonLayer';

function rateToBar(isNew, data, price) {
    if (isNew) {
        data[data.length - 1].close = parseFloat(price);
        if (data[data.length - 1].high < parseFloat(price)) {
            data[data.length - 1].high = parseFloat(price);
        }
        if (data[data.length - 1].low > parseFloat(price)) {
            data[data.length - 1].low = parseFloat(price);
        }
        data[data.length - 1].datetime = new Date().getTime();
    } else {
        data.push({
            close: parseFloat(price),
            high: parseFloat(price),
            low: parseFloat(price),
            open: parseFloat(price),
            datetime: new Date().getTime()
        });
    }
}

export default class extends React.Component {
    constructor(props) {
        super(props);
        this.chartRef = React.createRef();
        this.overlyingData = [];
        this.horizonData = [];
    }

    /**
     * 动态更新叠加品种
     * @param overlying
     * @param price
     * @param ktype
     */
    updateOverlying(overlying, price, ktype) {
        const { data } = overlying;
        if (data.length === 0) {
            data.push({
                close: parseFloat(price),
                high: parseFloat(price),
                low: parseFloat(price),
                open: parseFloat(price),
                datetime: new Date().getTime()
            });
        } else if (data.length === 1) {

        } else {
            const lastTime = parseInt(data[data.length - 2].datetime);
            const currentTime = new Date().getTime();
            if (ktype === 0) {
                // 1分钟线
                rateToBar(lastTime + 60 * 1000 < currentTime, data, price);
            } else if (ktype === 1) {
                // 5分钟线
                rateToBar(lastTime + 5 * 60 * 1000 < currentTime, data, price);
            } else if (ktype === 2) {
                // 15分钟
                rateToBar(lastTime + 15 * 60 * 1000 < currentTime, data, price);
            } else if (ktype === 3) {
                // 30分钟线
                rateToBar(lastTime + 30 * 60 * 1000 < currentTime, data, price);
            } else if (ktype === 4) {
                // 小时线
                rateToBar(lastTime + 60 * 60 * 1000 < currentTime, data, price);
            } else if (ktype === 5) {
                // 4小时线
                rateToBar(lastTime + 4 * 60 * 60 * 1000 < currentTime, data, price);
            } else if (ktype === 6) {
                // 日线
                rateToBar(lastTime + 24 * 60 * 60 * 1000 < currentTime, data, price);
            } else if (ktype === 7) {
                rateToBar(lastTime + 7 * 24 * 60 * 60 * 1000 < currentTime, data, price);
            } else if (ktype === 8) {
                rateToBar(lastTime + 30 * 24 * 60 * 60 * 1000 < currentTime, data, price);
            }
        }
        overlying.data = data;
        this.overlying.make();
        this.canvas.paint();
    }

    /**
     * 动态更新数据
     * **/
    updateRate(price, ktype) {
        const { data } = this.barLayer;
        if (data.length === 0) {
            data.push({
                close: parseFloat(price),
                high: parseFloat(price),
                low: parseFloat(price),
                open: parseFloat(price),
                datetime: new Date().getTime()
            });
        } else if (data.length === 1) {

        } else {
            const lastTime = parseInt(data[data.length - 2].datetime);
            const currentTime = new Date().getTime();
            if (ktype === 0) {
                // 1分钟线
                rateToBar(lastTime + 60 * 1000 > currentTime, data, price);
            } else if (ktype === 1) {
                // 5分钟线
                rateToBar(lastTime + 5 * 60 * 1000 > currentTime, data, price);
            } else if (ktype === 2) {
                // 15分钟
                rateToBar(lastTime + 15 * 60 * 1000 > currentTime, data, price);
            } else if (ktype === 3) {
                // 30分钟线
                rateToBar(lastTime + 30 * 60 * 1000 > currentTime, data, price);
            } else if (ktype === 4) {
                // 小时线
                rateToBar(lastTime + 60 * 60 * 1000 > currentTime, data, price);
            } else if (ktype === 5) {
                // 4小时线
                rateToBar(lastTime + 4 * 60 * 60 * 1000 > currentTime, data, price);
            } else if (ktype === 6) {
                // 日线
                rateToBar(lastTime + 24 * 60 * 60 * 1000 > currentTime, data, price);
            } else if (ktype === 7) {
                rateToBar(lastTime + 7 * 24 * 60 * 60 * 1000 > currentTime, data, price);
            } else if (ktype === 8) {
                rateToBar(lastTime + 30 * 24 * 60 * 60 * 1000 > currentTime, data, price);
            }
        }
        this.barLayer.data = data;
        this.drawLayer.xAxis = data.map(item => item.datetime);
        this.barLayer.make();
        this.canvas.paint();
    }

    componentWillUnmount() {
        OChart.remove(`${this.props.name}:onQuoteDrag`, this.onQuoteDrag);
        OChart.remove(`${this.props.name}:onQuoteDragEnd`, this.onQuoteDragEnd);
        OChart.remove(`${this.props.name}:onQuoteScale`, this.onQuoteScale);
        OChart.remove(`${this.props.name}:drawLine`, this.drawLine);
        OChart.remove(`${this.props.name}:onDrawLineMove`, this.onDrawLineMove);
        OChart.remove(`${this.props.name}:onDrawLineMoved`, this.onDrawLineMoved);
        OChart.remove(`${this.props.name}:deleteLine`, this.deleteLine);
        OChart.remove(`${this.props.name}:onDrawLineSelected`, this.onDrawLineSelected);
        OChart.remove(`${this.props.name}:editLine`, this.editLine);
        OChart.remove(`${this.props.name}:updateRate`, this.updateRate);
        OChart.remove(`${this.props.name}:setStyle`, this.setStyle);
        OChart.remove(`${this.props.name}:setCurrentPriceStyle`, this.setCurrentPriceStyle);
        OChart.remove(`${this.props.name}:setCurve`, this.setCurve);
        OChart.remove(`${this.props.name}:setMainQuota`, this.setMainQuota);
        OChart.remove(`${this.props.name}:addOverlying`, this.addOverlying);
        OChart.remove(`${this.props.name}:removeOverlying`, this.removeOverlying);
        OChart.remove(`${this.props.name}:updateOverlyingRate`, this.updateOverlyingRate);
        OChart.remove(`${this.props.name}:addHorizon`, this.addHorizon);
        OChart.remove(`${this.props.name}:setHorizonOnMove`, this.setHorizonOnMove);
        OChart.remove(`${this.props.name}:setHorizonOnSelected`, this.setHorizonOnSelected);
        OChart.remove(`${this.props.name}:removeHorizon`, this.removeHorizon);
        // 设置坐标样式
        OChart.remove(`${this.props.name}:setAxisStyle`, this.setAxisStyle);
        OChart.remove(`${this.props.name}:resize`, this.resize);
    }

    componentWillReceiveProps(nextProps, nextContext) {
        const { data, name = '' } = nextProps;
        if (data !== this.props.data) {
            this.barLayer.data = data;
            this.drawLayer.xAxis = data.map(item => item.datetime);
            this.barLayer.make();
            this.canvas.paint();
        }

        if (this.props.name !== name) {
            OChart.remove(`${this.props.name}:onQuoteDrag`, this.onQuoteDrag);
            OChart.remove(`${this.props.name}:onQuoteDragEnd`, this.onQuoteDragEnd);
            OChart.remove(`${this.props.name}:onQuoteScale`, this.onQuoteScale);
            OChart.remove(`${this.props.name}:drawLine`, this.drawLine);
            OChart.remove(`${this.props.name}:onDrawLineMove`, this.onDrawLineMove);
            OChart.remove(`${this.props.name}:onDrawLineMoved`, this.onDrawLineMoved);
            OChart.remove(`${this.props.name}:deleteLine`, this.deleteLine);
            OChart.remove(`${this.props.name}:onDrawLineSelected`, this.onDrawLineSelected);
            OChart.remove(`${this.props.name}:editLine`, this.editLine);
            OChart.remove(`${this.props.name}:updateRate`, this.updateRatex);
            OChart.remove(`${this.props.name}:setStyle`, this.setStyle);
            OChart.remove(`${this.props.name}:setCurrentPriceStyle`, this.setCurrentPriceStyle);
            OChart.remove(`${this.props.name}:setCurve`, this.setCurve);
            OChart.remove(`${this.props.name}:setMainQuota`, this.setMainQuota);
            OChart.remove(`${this.props.name}:addOverlying`, this.addOverlying);
            OChart.remove(`${this.props.name}:removeOverlying`, this.removeOverlying);
            OChart.remove(`${this.props.name}:updateOverlyingRate`, this.updateOverlyingRate);
            OChart.remove(`${this.props.name}:addHorizon`, this.addHorizon);
            OChart.remove(`${this.props.name}:setHorizonOnMove`, this.setHorizonOnMove);
            OChart.remove(`${this.props.name}:setHorizonOnSelected`, this.setHorizonOnSelected);
            OChart.remove(`${this.props.name}:removeHorizon`, this.removeHorizon);
            // 设置坐标样式
            OChart.remove(`${this.props.name}:setAxisStyle`, this.setAxisStyle);
            OChart.remove(`${this.props.name}:resize`, this.resize);

            OChart.on(`${name}:onQuoteDrag`, this.onQuoteDrag);
            OChart.on(`${name}:onQuoteDragEnd`, this.onQuoteDragEnd);
            OChart.on(`${name}:onQuoteScale`, this.onQuoteScale);
            OChart.on(`${name}:drawLine`, this.drawLine);
            OChart.on(`${name}:onDrawLineMove`, this.onDrawLineMove);
            OChart.on(`${name}:onDrawLineMoved`, this.onDrawLineMoved);
            OChart.on(`${name}:deleteLine`, this.deleteLine);
            OChart.on(`${name}:onDrawLineSelected`, this.onDrawLineSelected);
            OChart.on(`${name}:editLine`, this.editLine);
            OChart.on(`${name}:updateRate`, this.updateRatex);
            OChart.on(`${name}:setStyle`, this.setStyle);
            OChart.on(`${name}:setCurrentPriceStyle`, this.setCurrentPriceStyle);
            OChart.on(`${name}:setCurve`, this.setCurve);
            OChart.on(`${name}:setMainQuota`, this.setMainQuota);
            OChart.on(`${name}:addOverlying`, this.addOverlying);
            OChart.on(`${name}:removeOverlying`, this.removeOverlying);
            OChart.on(`${name}:updateOverlyingRate`, this.updateOverlyingRate);
            OChart.on(`${name}:addHorizon`, this.addHorizon);
            OChart.on(`${name}:setHorizonOnMove`, this.setHorizonOnMove);
            OChart.on(`${name}:setHorizonOnSelected`, this.setHorizonOnSelected);
            OChart.on(`${name}:removeHorizon`, this.removeHorizon);
            // 设置坐标样式
            OChart.on(`${name}:setAxisStyle`, this.setAxisStyle);
            OChart.on(`${name}:resize`, this.resize);
        }
    }

    onChartDrag = (e) => {
      if (this.barLayer.locked) {
        return;
      }
      if (this.barLayer.position.x + e.distanceX >= (this.barLayer.data.length - this.barLayer.barNum) * this.barLayer.barWidth) {
        this.barLayer.setPosition((this.barLayer.data.length - this.barLayer.barNum) * this.barLayer.barWidth, this.barLayer.position.y);
      } else if(this.barLayer.position.x <= -this.barLayer.width / 2){
        this.barLayer.setPosition(-this.barLayer.width / 2, this.barLayer.position.y);
      }else {
        this.barLayer.setPosition(this.barLayer.position.x + e.distanceX, this.barLayer.position.y);
      }
      this.barLayer.make();
      this.canvas.paint();
    }

    onChartScale = (e) => {
        if(this.barLayer.locked) {
            return;
        }
        if (e.nativeEvent.wheelDeltaY < 0) {
            if (this.barLayer.barNum < this.barLayer.data.length) {
                this.barLayer.barNum = Math.round(this.barLayer.barNum * 1.1);
                this.barLayer.make();
                this.canvas.paint();
            }
        } else {
            if (this.barLayer.barNum > 20) {
                this.barLayer.barNum = Math.round(this.barLayer.barNum * 0.9);
                this.barLayer.make();
                this.canvas.paint();
            }
        }
    }

    onChartDragEnd = (e) => {
      if (this.barLayer.locked) {
        return;
      }
      const accelerate = e.speedX > 0 ? 3000 : -3000; // 加速度200像素每秒
      const duration = Math.abs(e.speedX / accelerate);
      this.accelerateAction = new AccelerateAction(duration, {
        speedX: e.speedX,
        accelerateX: accelerate,
        beforeUpdate: (node, frame) => {
          if (node.position.x >= (this.barLayer.data.length - this.barLayer.barNum) * node.barWidth) {
            node.setPosition((this.barLayer.data.length - this.barLayer.barNum) * node.barWidth, node.position.y);
          } else if(node.position.x <= -this.barLayer.width / 2) {
            node.setPosition(-this.barLayer.width / 2, node.position.y);

          }
          node.make();
        }
      });
      this.barLayer.runAction(this.accelerateAction, (node, action) => {
        if (node.position.x >= (this.barLayer.data.length - this.barLayer.barNum) * node.barWidth) {
          node.stopAction(action);
          node.setPosition((this.barLayer.data.length - this.barLayer.barNum) * node.barWidth, node.position.y);
        } else if (node.position.x <= -this.barLayer.width / 2) {
          node.stopAction(action);
          node.setPosition(-this.barLayer.width / 2, node.position.y);
        }
      });
    }

    onQuoteDrag = (e) => {
        this.onChartDrag(e);
    }

    onQuoteDragEnd = (e) => {
        this.onChartDragEnd(e);
    }

    onQuoteScale = (e) => {
        this.onChartScale(e);
    }

    drawLine = (options) => {
        // 线条绘制监听
        const x1 = Math.round(
            (this.barLayer.barEnd - this.barLayer.barStart) / 3 + this.barLayer.barStart
        );
        const x2 = Math.round(
            (this.barLayer.barEnd - this.barLayer.barStart) / 3 * 2 + this.barLayer.barStart
        );
        const price1 = (this.barLayer.max - this.barLayer.min) / 3 + this.barLayer.min;
        const price2 = (this.barLayer.max - this.barLayer.min) / 3 * 2 + this.barLayer.min;
        const point1 = {
            date: this.barLayer.data[x1].datetime,
            price: price1,
        };
        const point2 = {
            date: this.barLayer.data[x2].datetime,
            price: price2,
        };
        const target = {
            point1,
            point2,
        };
        if (options.type === 0) {
            target.type = 0;
        } else if (options.type === 1) {
            target.type = 1;
        } else if (options.type === 2) {
            target.type = 2;
            target.rules = options.rules || [0, 23.6, 38.2, 50, 61.8, 80.9, 100];
        } else if(options.type === 3) {
            target.type = 3;
        } else if(options.type === 4) {
            target.type = 4;
        } else {
            target.type = 0;
        }
        target.color = options.color;
        target.isSelected = true;
        this.drawLayer.clearSelected();
        this.drawLayer.lines.push(target);
        this.drawLayer.make();
        this.canvas.paint();
        options.onCreated && options.onCreated(this.drawLayer.lines);
    }

    onDrawLineMove = ({callback}) => {
        this.drawLayer.onLineMove = (line) => {
            this.barLayer.locked = true;
            callback && callback(line);
        };
    }

    onDrawLineMoved = ({callback}) => {
        this.drawLayer.onLineMoved = (line) => {
            this.barLayer.locked = false;
            callback && callback(line);
        };
    }

    deleteLine = ({uuid}) => {
        const index = this.drawLayer.lines.findIndex(item => item.uuid === uuid);
        if (index >= 0) {
            this.drawLayer.lines.splice(index, 1);
            this.drawLayer.make();
            this.canvas.paint();
        }
    }

    onDrawLineSelected = ({callback}) => {
        console.log('onSelected', callback);
        this.drawLayer.onSelected = callback;
    }

    editLine = (options) => {
        const index = this.drawLayer.lines.findIndex(item => item.uuid === options.uuid);
        if(index >= 0){
            this.drawLayer.lines[index].color = options.color || this.drawLayer.lines[index].color;
            this.drawLayer.make();
            this.canvas.paint();
        }
    }

    updateRatex = (options) => {
        // 更新数据
        this.updateRate(options.price, options.ktype);
    }

    setStyle = (options) => {
        // 设置图表样式
        this.barLayer.lineType = options.lineType === undefined ? this.barLayer.lineType : options.lineType;
        this.barLayer.lineColor = options.lineColor || this.barLayer.lineColor;
        if (options.up) {
            this.barLayer.redColor = options.up.color || this.barLayer.redColor;
            this.barLayer.redHollow = options.up.solid === true;
        }
        if (options.down) {
            this.barLayer.greenColor = options.down.color || this.barLayer.greenColor;
            this.barLayer.greenHollow = options.down.solid === true;
        }
        this.barLayer.make();
        this.canvas.paint();
    }

    setCurrentPriceStyle = (options) => {
        this.priceLine.visible = options.visible === undefined ? this.priceLine.visible : options.visible;
        this.priceLine.color = options.color || this.priceLine.color;
        this.priceLine.backgroundColor = options.backgroundColor || this.priceLine.backgroundColor;
        this.priceLine.size = options.size || this.priceLine.size;
        this.priceLine.make();
        this.canvas.paint();
    }

    setCurve = (options) => {
        this.curveLayer.visible = options.visible === undefined ? this.priceLine.visible : options.visible;
        if (this.curveLayer.visible === false) {
            this.curveLayer.onStop();
        }
        this.curveLayer.color = options.color || this.curveLayer.color;
        this.curveLayer.backgroundColor = options.backgroundColor || this.curveLayer.backgroundColor;
        this.curveLayer.fontColor = options.fontColor || this.curveLayer.fontColor;
        this.curveLayer.size = options.size || this.curveLayer.size;
        if (options.onCurve) {
            this.onCurveCallback = options.onCurve;
        }
        if (options.onCurveEnd) {
            this.onCurveEnd = options.onCurveEnd;
        }
        if (options.onCurveLabel) {
            this.curveLayer.processData = options.onCurveLabel;
        }
    }

    setMainQuota = (options) => {
        this.indicatorLayer.name = options.quota;
        this.indicatorLayer.params = options.params;
        this.barLayer.make();
        this.canvas.paint();
    }

    addOverlying = (options) => {
        // 添加叠加品种
        let overlyings = this.overlyingData.filter(item => item.id === options.id);
        if (overlyings.length > 0) {
            let overlying = overlyings[0];
            overlying.data = options.data || overlying.data;
            if (options.up) {
                if (overlying.up) {
                    overlying.up.color = options.up.color || overlying.up.color;
                    overlying.up.solid = options.up.solid || overlying.up.solid;
                } else {
                    overlying.up = options.up;
                }
            }
            if (options.down) {
                if (overlying.down) {
                    overlying.down.color = options.down.color || overlying.down.color;
                    overlying.down.solid = options.down.solid || overlying.down.solid;
                } else {
                    overlying.down = options.down;
                }
            }
            overlying.lineType = options.lineType || overlying.lineType;
            overlying.lineColor = options.lineColor || overlying.lineColor;
        } else {
            this.overlyingData.push(options);
        }
        this.overlying.data = this.overlyingData;
        this.overlying.make();
        this.canvas.paint();
    }

    removeOverlying = ({overlyingId}) => {
        let index = this.overlyingData.findIndex(item => item.id = overlyingId);
        if (index >= 0) {
            this.overlyingData.splice(index, 1);
            this.overlying.data = this.overlyingData;
            this.overlying.make();
            this.canvas.paint();
        }
    }

    updateOverlyingRate = (options) => {
        let index = this.overlyingData.findIndex(item => item.id === options.id);
        if (index >= 0) {
            let overlying = this.overlyingData[index];
            this.updateOverlying(overlying, options.price, options.ktype);
        }
    }

    addHorizon = (options) => {
        this.horizonLayer.onMoved = options.onMove || this.horizonLayer.onMoved;
        this.horizonLayer.onSelected = options.onSelected || this.horizonLayer.onSelected;
        if (options.lines) {
            if (options.lines instanceof Array) {
                options.lines.forEach(item => {
                    const index = this.horizonData.findIndex(vo => vo.id === item.id);
                    if (index === -1) {
                        this.horizonData.push(item);
                    } else {
                        this.horizonData[index].price = item.price || this.horizonData[index].price;
                        this.horizonData[index].color = item.color || this.horizonData[index].color;
                        this.horizonData[index].movable = item.movable || this.horizonData[index].movable;
                        this.horizonData[index].selectable = item.selectable || this.horizonData[index].selectable;
                        this.horizonData[index].legend = item.legend || this.horizonData[index].legend;
                    }
                });
            } else if (options.lines instanceof Object) {
                const index = this.horizonData.findIndex(vo => vo.id === options.lines.id);
                if (index === -1) {
                    this.horizonData.push(options.lines);
                } else {
                    this.horizonData[index].price = options.lines.price || this.horizonData[index].price;
                    this.horizonData[index].color = options.lines.color || this.horizonData[index].color;
                    this.horizonData[index].movable = options.lines.movable || this.horizonData[index].movable;
                    this.horizonData[index].selectable = options.lines.selectable || this.horizonData[index].selectable;
                    this.horizonData[index].legend = options.lines.legend || this.horizonData[index].legend;
                }
            }
            this.horizonLayer.data = this.horizonData;
            this.horizonLayer.make();
            this.canvas.paint();
        }
    }

    setHorizonOnMove = (options) => {
        this.horizonLayer.onMoved = options.onMove || this.horizonLayer.onMoved;
    }

    setHorizonOnSelected = (options) => {
        this.horizonLayer.onSelected = options.onSelected || this.horizonLayer.onSelected;
    }

    removeHorizon = (options) => {
        const { id } = options;
        const index = this.horizonData.findIndex(item => item.id === id);
        if (index !== -1) {
            this.horizonData.splice(index, 1);
            this.horizonLayer.data = this.horizonData;
            this.horizonLayer.make();
            this.canvas.paint();
        }
    }

    setAxisStyle = (styles) => {
        this.axisLayer.xAxisGraduations = styles.xAxisGraduations || this.axisLayer.xAxisGraduations;
        this.axisLayer.yAxisGraduations  = styles.yAxisGraduations || this.axisLayer.yAxisGraduations;
        this.axisLayer.yAxisMax = styles.yAxisMax || this.axisLayer.yAxisMax;
        this.axisLayer.yAxisMin = styles.yAxisMin || this.axisLayer.yAxisMin;
        this.axisLayer.xAxisMax = styles.xAxisMax || this.axisLayer.xAxisMax;
        this.axisLayer.xAxisMin = styles.xAxisMin || this.axisLayer.xAxisMin;
        this.axisLayer.xAxisRender = styles.xAxisRender || this.axisLayer.xAxisRender;
        this.axisLayer.yAxisRender = styles.yAxisRender || this.axisLayer.yAxisRender;
        this.axisLayer.xAxisPosition = styles.xAxisPosition || this.axisLayer.xAxisPosition;
        this.axisLayer.yAxisPosition = styles.yAxisPosition || this.axisLayer.yAxisPosition;
        this.axisLayer.yAxisDirect = styles.yAxisDirect || this.axisLayer.yAxisDirect;
        this.axisLayer.make();
        this.canvas.paint();
    }

    resize = ({callback}) => {
        if (
            this.chartRef.current !== undefined
            && this.chartRef.current !== null
        ) {
            this.save();
            this.chartRef.current.innerHTML = '';
            setTimeout(() => {
                this.init();
                this.restore();
                callback && callback();
            }, 0)
        }
    }

    componentDidMount() {
      const { name = '' } = this.props;
      this.init();
      window.addEventListener('resize', (e) => {
          if (
              this.chartRef.current !== undefined
              && this.chartRef.current !== null
          ) {
              this.save();
              this.chartRef.current.innerHTML = '';
              setTimeout(() => {
                  this.init();
                  this.restore();
              }, 0);

          }
      });
      OChart.on(`${name}:onQuoteDrag`, this.onQuoteDrag);
      OChart.on(`${name}:onQuoteDragEnd`, this.onQuoteDragEnd);
      OChart.on(`${name}:onQuoteScale`, this.onQuoteScale);
      OChart.on(`${name}:drawLine`, this.drawLine);
      OChart.on(`${name}:onDrawLineMove`, this.onDrawLineMove);
      OChart.on(`${name}:onDrawLineMoved`, this.onDrawLineMoved);
      OChart.on(`${name}:deleteLine`, this.deleteLine);
      OChart.on(`${name}:onDrawLineSelected`, this.onDrawLineSelected);
      OChart.on(`${name}:editLine`, this.editLine);
      OChart.on(`${name}:updateRate`, this.updateRatex);
      OChart.on(`${name}:setStyle`, this.setStyle);
      OChart.on(`${name}:setCurrentPriceStyle`, this.setCurrentPriceStyle);
      OChart.on(`${name}:setCurve`, this.setCurve);
      OChart.on(`${name}:setMainQuota`, this.setMainQuota);
      OChart.on(`${name}:addOverlying`, this.addOverlying);
      OChart.on(`${name}:removeOverlying`, this.removeOverlying);
      OChart.on(`${name}:updateOverlyingRate`, this.updateOverlyingRate);
      OChart.on(`${name}:addHorizon`, this.addHorizon);
      OChart.on(`${name}:setHorizonOnMove`, this.setHorizonOnMove);
      OChart.on(`${name}:setHorizonOnSelected`, this.setHorizonOnSelected);
      OChart.on(`${name}:removeHorizon`, this.removeHorizon);
      // 设置坐标样式
      OChart.on(`${name}:setAxisStyle`, this.setAxisStyle);
      OChart.on(`${name}:resize`, this.resize);
    }

    save() {
        this.store = {
            drawLines: this.drawLayer.lines,
            onLineMove: this.drawLayer.onLineMove,
            onLineMoved: this.drawLayer.onLineMoved,
            onSelected: this.drawLayer.onSelected,
            styles: {
                lineType: this.barLayer.lineType,
                lineColor: this.barLayer.lineColor,
                redColor: this.barLayer.redColor,
                redHollow: this.barLayer.redHollow,
                greenColor: this.barLayer.greenColor,
                greenHollow: this.barLayer.greenHollow,
            },
            priceStyle: {
                visible: this.priceLine.visible,
                color: this.priceLine.color,
                backgroundColor: this.priceLine.backgroundColor,
                size: this.priceLine.size
            },
            curve: {
                visible: this.curveLayer.visible,
                color: this.curveLayer.color,
                backgroundColor: this.curveLayer.backgroundColor,
                fontColor: this.curveLayer.fontColor,
                size: this.curveLayer.size,
                onCurveCallback: this.curveLayer.onCurveCallback,
                onCurveEnd: this.curveLayer.onCurveEnd,
                processData: this.curveLayer.processData
            },
            mainIndicator: {
                name: this.indicatorLayer.name,
                params: this.indicatorLayer.params
            },
            horizon: {
                onMoved: this.horizonLayer.onMoved,
                onSelected: this.horizonLayer.onSelected,
            },
            axis: {
                xAxisGraduations: this.axisLayer.xAxisGraduations,
                yAxisGraduations: this.axisLayer.yAxisGraduations,
                yAxisMax: this.axisLayer.yAxisMax,
                yAxisMin: this.axisLayer.yAxisMin,
                xAxisMax: this.axisLayer.xAxisMax,
                xAxisMin: this.axisLayer.xAxisMin,
                xAxisRender: this.axisLayer.xAxisRender,
                yAxisRender: this.axisLayer.yAxisRender,
                xAxisPosition: this.axisLayer.xAxisPosition,
                yAxisPosition: this.axisLayer.yAxisPosition,
                yAxisDirect: this.axisLayer.yAxisDirect
            }
        }
    }

    restore() {
        if (this.store) {
            this.overlying.data = this.overlyingData;
            this.horizonLayer.data = this.horizonData;
            this.drawLayer.lines = this.store.drawLines;
            this.drawLayer.onLineMove = this.store.onLineMove;
            this.drawLayer.onLineMoved = this.store.onLineMoved;
            this.drawLayer.onSelected = this.store.onSelected;
            Object.assign(this.barLayer, this.store.styles);
            Object.assign(this.priceLine, this.store.priceStyle);
            Object.assign(this.curveLayer, this.store.curve);
            Object.assign(this.indicatorLayer, this.store.mainIndicator);
            Object.assign(this.horizonLayer, this.store.horizon);
            Object.assign(this.axisLayer, this.store.axis);
        }
    }

    init() {
        const { data, lines = [], name = '' } = this.props;
        this.canvas = new Canvas({
            ele: this.chartRef.current,
            canAction: false,
        });
        this.axisLayer = new AxisLayer(this.canvas, {
            yAxisMax: 100,
            yAxisMin: 0,
            xAxisLabels: [],
            xAxisPosition: AxisLayer.AxisPosition.BLOCK,
            xAxisGraduations: 5,
            yAxisGraduations: 3,
            yAxisRender: (data) => {
                return {
                    text: parseFloat(data).toFixed(2),
                    size: 20,
                };
            },
        });
        this.barLayer = new KBarLayer(this.canvas, {
            width: this.canvas.width,
            height: this.canvas.height - 160,
            data,
            barNum: 100,
        });
        this.barLayer.setPosition(-120, 80);
        this.indicatorLayer = new IndicatorLayer(this.canvas, {
            width: this.canvas.width,
            height: this.canvas.height - 160,
            data,
            name: 'ma'
        });
        this.indicatorLayer.setPosition(0, 80);
        this.barLayer.indicatorLayer = this.indicatorLayer;
        this.canvas.addChild(this.axisLayer, this.barLayer, this.indicatorLayer);
        this.barLayer.addEventListener(Event.EVENT_TAP, (e) => {
            if (this.accelerateAction !== null && this.accelerateAction !== undefined) {
                this.barLayer.stopAction(this.accelerateAction);
            }
        });
        this.barLayer.addEventListener(Event.EVENT_DRAG, (e) => {
            this.onChartDrag(e);
        });
        this.barLayer.addEventListener(Event.EVENT_DRAG_END, (e) => {
            this.onChartDragEnd(e);
        });

        this.barLayer.addEventListener(Event.EVENT_MOUSE_WHEEL, (e) => {
            this.onChartScale(e);
        });

        this.drawLayer = new DrawLayer(this.canvas, {
            width: this.canvas.width,
            height: this.canvas.height,
            lines,
            onLineMove: () => {
                this.barLayer.locked = true;
            },
            onLineMoved: () => {
                this.barLayer.locked = false;
            },
        });
        this.drawLayer.setPosition(0, 0);
        this.canvas.addChild(this.drawLayer);
        this.priceLine = new PriceLine(this.canvas, {
            width: this.canvas.width,
            height: this.canvas.height - 160,
        });
        this.priceLine.visible = false;
        this.canvas.addChild(this.priceLine);
        this.curveLayer = new CurveLayer(this.canvas, {
            width: this.canvas.width,
            height: this.canvas.height
        });
        this.curveLayer.addEventListener(this.canvas.version === 'PC' ? Event.EVENT_LONG_CLICK : Event.EVENT_LONG_TAP, (e) => {
            const point = e.eventPoint;
            this.barLayer.locked = true;
            this.curveLayer.locked = true;
            this.curveLayer.onRun(point, (shift, price) => {
                let bar = {
                    open: 0,
                    high: 0,
                    low: 0,
                    close: 0,
                    datetime: 0,
                };
                if (this.barLayer.data[this.barLayer.barStart + shift] !== undefined) {
                    bar = this.barLayer.data[this.barLayer.barStart + shift];
                }
                this.onCurveCallback && this.onCurveCallback({
                    shift,
                    bar,
                    point,
                    price,
                });
            });
            this.canvas.paint();
        });
        this.curveLayer.addEventListener(this.canvas.version === 'PC' ? Event.EVENT_MOUSE_MOVE : Event.EVENT_TOUCH_MOVE, (e) => {
            if (this.curveLayer.locked) {
                const point = e.eventPoint;
                this.curveLayer.onRun(point, (shift, price) => {
                    let bar = {
                        open: 0,
                        high: 0,
                        low: 0,
                        close: 0,
                        datetime: 0,
                    };
                    if (this.barLayer.data[this.barLayer.barStart + shift] !== undefined) {
                        bar = this.barLayer.data[this.barLayer.barStart + shift];
                    }
                    this.onCurveCallback && this.onCurveCallback({
                        shift,
                        bar,
                        point,
                        price
                    });
                });
                this.canvas.paint();
            }
        });
        this.curveLayer.addEventListener(this.canvas.version === 'PC' ? Event.EVENT_MOUSE_UP : Event.EVENT_TOUCH_END, (e) => {
            this.curveLayer.locked = false;
            const ret = this.onCurveEnd && this.onCurveEnd();
            if (ret === undefined || ret === false) {
                this.curveLayer.onStop();
            }
        });
        this.curveLayer.visible = false;
        this.canvas.addChild(this.curveLayer);
        this.overlying = new OverlyingLayer(this.canvas, {
            width: this.canvas.width,
            height: this.canvas.height - 160,
        });
        this.overlying.setPosition(0, 80);
        this.canvas.addChild(this.overlying);
        this.horizonLayer = new HorizonLayer(this.canvas, {
            width: this.canvas.width,
            height: this.canvas.height,
            data: this.horizonData,
        });
        this.canvas.addChild(this.horizonLayer);
        this.barLayer.setOnMaked((layer, option) => {
            const { max, min, start, end, barWidth, yDelta } = option;
            let yAxisMax = max + 80 / yDelta;
            let yAxisMin = min - 80 / yDelta;
            this.axisLayer.yAxisMax =  yAxisMax;
            this.axisLayer.yAxisMin = yAxisMin;
            this.drawLayer.start = start;
            this.drawLayer.end = end;
            this.drawLayer.min = yAxisMin;
            this.drawLayer.max = yAxisMin;
            this.drawLayer.xStep = barWidth;
            this.drawLayer.yStep = yDelta;
            this.priceLine.price = this.barLayer.data[this.barLayer.data.length - 1].close;
            this.priceLine.yStep = yDelta;
            this.priceLine.yBase = yAxisMin;
            this.curveLayer.xStep = barWidth;
            this.curveLayer.yStep = yDelta;
            this.curveLayer.min = yAxisMin;
            this.curveLayer.max = yAxisMax;
            this.overlying.xStep = barWidth;
            this.overlying.start = this.barLayer.data.length - start;
            this.overlying.end = this.barLayer.data.length - end;
            this.overlying.data = this.overlyingData;
            this.horizonLayer.yStep = yDelta;
            this.horizonLayer.base = yAxisMin;
            this.horizonLayer.make();
            this.overlying.make();
            this.priceLine.make();
            this.drawLayer.make();
            this.axisLayer.make();
            OChart.emit(`${name}:onChartMaked`, {
                start,
                end,
                xStep: barWidth,
                yStep: yDelta,
                max: yAxisMax,
                min: yAxisMin
            });
        });

        this.axisLayer.make();
        this.barLayer.make();
        this.canvas.paint();
    }

    render() {
        const { className = '' } = this.props;
        return (
            <div className={className} ref={this.chartRef} />
        )
    }

}
